package com.tkm.builtinTypes.functions

fun main(vararg args: String) {
    println(args.contentToString())

    //  Foo参数就是bar方法的receiver
    //  转换为函数，则需要将Foo参数作为第一个入参
    //  Foo, String, Long) -> Any = Foo.(String, Long) -> Any = Function3<Foo, String, Long, Any>
    val x: (Foo, String, Long) -> Any = Foo::bar
    val y: Foo.(String, Long) -> Any = Foo::bar
    val z: Function3<Foo, String, Long, Any> = Foo::bar

    yy(x)
    yy(y)
    yy(z)

    //  函数引用
    val f: () -> Unit = ::foo
    val g: (Int) -> String = ::foo
    println(g(20))

    //  绑定了receiver的函数引用
    val foo = Foo()
    val m: (String, Long) -> Any = foo::bar

    multiParams(1, 2, 3)
    multiParams(1, 2, 3, 4 ,5)

    //  解构Triple
    val (p1, p2, p3) = multiReturnValues()
    val r1 = p1 + p2
    val r2 = p2 + p3

    //  具名参数：显式指定形参
    defaultParams(y = "Hello")
    defaultParams(x = 10, "World")
    defaultParams(20, "Kotlin")
    defaultParams(100, "ZCCP", 90L)
}

class Foo {
    //  函数vs方法
    //  方法可以认为是函数的一种特殊类型
    //  从形式上，有receiver的函数即为方法
    fun bar(p0: String, p1: Long): Any {
        return p0 + p1
    }
}

fun yy(p: (Foo, String, Long) -> Any) {

}

//  实际上返回值类型为Unit，可省略，编译器自动推断
fun foo() {
    println("foo1 called") }

//  Kotlin中函数的重载
fun foo(p0: Int): String {
    println("foo2 called $p0")
    return "foo"
}

//  默认参数
//  如果默认参数不靠后，则调用时，需要使用具名参数显式指明形参
fun defaultParams(x: Int = 5, y: String, z: Long = 100L) {}

//  变长参数
fun multiParams(vararg x: Int) {
    println(x.contentToString())
}

//  多个返回值
fun multiReturnValues(): Triple<Int, Double, Long> {
    return Triple(114, 2.0, 514L)
}

